import jade.content.lang.sl.SLCodec;
import jade.content.onto.basic.*;

import jade.core.*;
import jade.core.behaviours.*;

import jade.domain.*;
import jade.domain.introspection.*;
import jade.domain.FIPAAgentManagement.*;
import jade.domain.JADEAgentManagement.*;

import jade.lang.acl.*;

import jade.proto.*;

import jade.wrapper.*;

import java.util.*;

public class eventAgent extends Agent
{
	Object[] arguments;
	eventHandlerBehaviour behaviour1;
	acceptNewRequestsBehaviour behaviour2;
	ArrayList <String> addedContainerList;
	ArrayList <String> removedContainerList;
	ArrayList <String> bornAgentList;
	ArrayList <String> deadAgentList;
	ArrayList <String> suspendedAgentList;
	ArrayList <String> resumedAgentList;
	ArrayList <String> movedAgentList;
	ArrayList <String> killContainerRequestedList;
	ArrayList <String> shutdownPlatformRequestedList;
	

	protected void setup()
	{
		arguments = getArguments();
		if(arguments!=null)
		{
			for(int i=0;i<arguments.length;i++)
			{
				System.out.println(String.valueOf(arguments[i]));
			}
		}

		addedContainerList = new ArrayList <String> (10);
		removedContainerList = new ArrayList <String> (10);
		bornAgentList = new ArrayList <String> (10);
		deadAgentList = new ArrayList <String> (10);
		suspendedAgentList = new ArrayList <String> (10);
		resumedAgentList = new ArrayList <String> (10);
		movedAgentList = new ArrayList <String> (10);
		killContainerRequestedList = new ArrayList <String> (10);
		shutdownPlatformRequestedList = new ArrayList <String> (10);
		System.out.println(getLocalName() + ": I am an event agent.");
		
		//Performs registration actions
		initialize();
		
		//Description used to register with the DF agent
		DFAgentDescription agentDescription = new DFAgentDescription();
		
		//Sets the name used in the description
		agentDescription.setName(getAID());
		
		//Used to decide what kind of  service you are looking for
		ServiceDescription agentServiceTemplate = new ServiceDescription();
		
		//String description of the Service
		agentServiceTemplate.setType("Event_Agent");

		//Set Service template name to uniquely identify service
		agentServiceTemplate.setName(getLocalName()+"-Event_Agent");
	
		//Set template to reflect this agents Service using the Service Template
		agentDescription.addServices(agentServiceTemplate);
		
		try 
		{
			//Register this agent's Service
			DFService.register(this, agentDescription);
			System.out.println("I just registered with the DF");
		}
		catch (FIPAException fe) 
		{
			fe.printStackTrace();
		}
		
		behaviour1 = new eventHandlerBehaviour();
		behaviour2 = new acceptNewRequestsBehaviour();
		addBehaviour(behaviour1);
		addBehaviour(behaviour2);
	}

	protected void takeDown()
	{
		//Destrucion of agent goes here
	}

	protected void afterMove()
	{
		initialize();
		behaviour1.reset();
		behaviour2.reset();
	}

	protected void initialize()
	{
		//Used to register the FIPA_SL codec with this agent
		getContentManager().registerLanguage(new SLCodec(), FIPANames.ContentLanguage.FIPA_SL);
		
		//Used to register JADE Management Ontology with this agent
		getContentManager().registerOntology(JADEManagementOntology.getInstance());
	}

	private class acceptNewRequestsBehaviour extends CyclicBehaviour 
	{
		String messageContent;
		String name;
	
		public void action() 
		{
			MessageTemplate language = MessageTemplate.MatchLanguage("Event");
			MessageTemplate ontology = MessageTemplate.MatchOntology("Event");
			MessageTemplate template = MessageTemplate.and(language,ontology);
			jade.lang.acl.ACLMessage msgRx = receive(template);
			if (msgRx != null) 
			{
				messageContent = new String(msgRx.getContent());

				switch(msgRx.getPerformative())
				{
					case jade.lang.acl.ACLMessage.REQUEST:

					name = msgRx.getSender().getName();
					System.out.println(name);
					
					switch(messageContent.charAt(2))
					{
						case 'a':
						case 'A':
						//added containers
						if(!addedContainerList.contains(name))
						{
							if((messageContent.charAt(0)=='a')||(messageContent.charAt(0)=='A'))
							{
								addedContainerList.add(name);
							}
						}
						else
						{
							if((messageContent.charAt(0)=='r')||(messageContent.charAt(0)=='R'))
							{
								addedContainerList.remove(addedContainerList.indexOf(name));
							}	
						}
						
						break;
						case 'b':
						case 'B':
						//born agents
						if(!bornAgentList.contains(name))
						{
							if((messageContent.charAt(0)=='a')||(messageContent.charAt(0)=='A'))
							{
								bornAgentList.add(name);
							}
						}
						else
						{
							if((messageContent.charAt(0)=='r')||(messageContent.charAt(0)=='R'))
							{
								bornAgentList.remove(bornAgentList.indexOf(name));
							}
								
						}
						break;
						case 'd':
						case 'D':
						//dead agents
						if(!deadAgentList.contains(name))
						{
							if((messageContent.charAt(0)=='a')||(messageContent.charAt(0)=='A'))
							{
								deadAgentList.add(name);
							}
						}
						else
						{
							if((messageContent.charAt(0)=='r')||(messageContent.charAt(0)=='R'))
							{
								deadAgentList.remove(deadAgentList.indexOf(name));
							}
								
						}
						break;
						case 'k':
						case 'K':
						//kill container
						if(!killContainerRequestedList.contains(name))
						{
							if((messageContent.charAt(0)=='a')||(messageContent.charAt(0)=='A'))
							{
								killContainerRequestedList.add(name);
							}
						}
						else
						{
							if((messageContent.charAt(0)=='r')||(messageContent.charAt(0)=='R'))
							{
								killContainerRequestedList.remove(killContainerRequestedList.indexOf(name));
							}
								
						}
						break;
						case 'm':
						case 'M':
						//moved agent
						if(!movedAgentList.contains(name))
						{
							if((messageContent.charAt(0)=='a')||(messageContent.charAt(0)=='A'))
							{
								movedAgentList.add(name);
							}
						}
						else
						{
							if((messageContent.charAt(0)=='r')||(messageContent.charAt(0)=='R'))
							{
								movedAgentList.remove(movedAgentList.indexOf(name));
							}
								
						}
						break;
						case 'r':
						case 'R':
						//removed container
						//resumed agent
						if((messageContent.charAt(4)=='m')||(messageContent.charAt(4)=='M'))
						{
							if(!removedContainerList.contains(name))
							{
								if((messageContent.charAt(0)=='a')||(messageContent.charAt(0)=='A'))
								{
									removedContainerList.add(name);
								}
							}
							else
							{
								if((messageContent.charAt(0)=='r')||(messageContent.charAt(0)=='R'))
								{
									removedContainerList.remove(removedContainerList.indexOf(name));
								}
									
							}
						}
						if((messageContent.charAt(4)=='s')||(messageContent.charAt(4)=='S'))
						{
							if(!resumedAgentList.contains(name))
							{
								if((messageContent.charAt(0)=='a')||(messageContent.charAt(0)=='A'))
								{
									resumedAgentList.add(name);
								}
							}
							else
							{
								if((messageContent.charAt(0)=='r')||(messageContent.charAt(0)=='R'))
								{
									resumedAgentList.remove(resumedAgentList.indexOf(name));
								}
							}	
						}
						break;
						case 's':
						case 'S':
						//suspended agent
						//shutdownplatform
						if((messageContent.charAt(3)=='u')||(messageContent.charAt(3)=='U'))
						{
							if(!suspendedAgentList.contains(name))
							{
								if((messageContent.charAt(0)=='a')||(messageContent.charAt(0)=='A'))
								{
									suspendedAgentList.add(name);
								}
							}
							else
							{
								if((messageContent.charAt(0)=='r')||(messageContent.charAt(0)=='R'))
								{
									suspendedAgentList.remove(suspendedAgentList.indexOf(name));
								}
									
							}
						}
						if((messageContent.charAt(3)=='h')||(messageContent.charAt(3)=='H'))
						{
							if(!shutdownPlatformRequestedList.contains(name))
							{
								if((messageContent.charAt(0)=='a')||(messageContent.charAt(0)=='A'))
								{
									shutdownPlatformRequestedList.add(name);
								}
							}
							else
							{
								if((messageContent.charAt(0)=='r')||(messageContent.charAt(0)=='R'))
								{
									shutdownPlatformRequestedList.remove(shutdownPlatformRequestedList.indexOf(name));
								}
							}	
						}
						break;
							
					}
					break;
				}		
			}
			else
			{ 
				block();
			}
		}
	}

	private class eventHandlerBehaviour extends AMSSubscriber
	{
		protected void installHandlers(Map handlers) 
		{
			EventHandler addedContainerHandler = new EventHandler() 
			{
				public void handle(Event ev) 
				{
					AddedContainer ac = (AddedContainer) ev;
					String messageContent = "AddedContainer:";
					messageContent=messageContent+ac.getContainer().getName();
					jade.lang.acl.ACLMessage message=new jade.lang.acl.ACLMessage(jade.lang.acl.ACLMessage.INFORM);
					for(int i=0;i<addedContainerList.size();i++)
					{
						message.addReceiver(new AID(addedContainerList.get(i), AID.ISGUID));
					}
					message.setLanguage("Event");
					message.setOntology("Event");
					message.setContent(messageContent);
					send(message);
					System.out.println(messageContent);
				}
			};
			handlers.put(IntrospectionVocabulary.ADDEDCONTAINER,addedContainerHandler);
			
			EventHandler removedContainerHandler = new EventHandler() 
			{
				public void handle(Event ev) 
				{
					RemovedContainer rc = (RemovedContainer) ev;
					String messageContent = "RemovedContainer:";
					messageContent=messageContent+rc.getContainer().getName();
					jade.lang.acl.ACLMessage message=new jade.lang.acl.ACLMessage(jade.lang.acl.ACLMessage.INFORM);
					for(int i=0;i<removedContainerList.size();i++)
					{
						message.addReceiver(new AID(removedContainerList.get(i), AID.ISGUID));
					}
					message.setLanguage("Event");
					message.setOntology("Event");
					message.setContent(messageContent);
					send(message);
					System.out.println(messageContent);
				}
			};
			handlers.put(IntrospectionVocabulary.REMOVEDCONTAINER,removedContainerHandler);
			
			EventHandler bornAgentHandler = new EventHandler() 
			{
				public void handle(Event ev) 
				{
					BornAgent ba = (BornAgent) ev;
					String messageContent = "BornAgent:";
					messageContent=messageContent+ba.getAgent().getName();
					jade.lang.acl.ACLMessage message=new jade.lang.acl.ACLMessage(jade.lang.acl.ACLMessage.INFORM);
					for(int i=0;i<bornAgentList.size();i++)
					{
						message.addReceiver(new AID(bornAgentList.get(i), AID.ISGUID));
					}
					message.setLanguage("Event");
					message.setOntology("Event");
					message.setContent(messageContent);
					send(message);
					System.out.println(messageContent);
				}
			};
			handlers.put(IntrospectionVocabulary.BORNAGENT,bornAgentHandler);

			EventHandler deadAgentHandler = new EventHandler() 
			{
				public void handle(Event ev) 
				{
					DeadAgent da = (DeadAgent) ev;
					String messageContent = "DeadAgent:";
					messageContent=messageContent+da.getAgent().getName();
					jade.lang.acl.ACLMessage message=new jade.lang.acl.ACLMessage(jade.lang.acl.ACLMessage.INFORM);
					for(int i=0;i<deadAgentList.size();i++)
					{
						message.addReceiver(new AID(deadAgentList.get(i), AID.ISGUID));
					}
					message.setLanguage("Event");
					message.setOntology("Event");
					message.setContent(messageContent);
					send(message);
					System.out.println(messageContent);
				}
			};
			handlers.put(IntrospectionVocabulary.DEADAGENT,deadAgentHandler);
			
			EventHandler suspendedAgentHandler = new EventHandler() 
			{
				public void handle(Event ev) 
				{
					SuspendedAgent sa = (SuspendedAgent) ev;
					String messageContent = "SuspendedAgent:";
					messageContent=messageContent+sa.getAgent().getName();
					jade.lang.acl.ACLMessage message=new jade.lang.acl.ACLMessage(jade.lang.acl.ACLMessage.INFORM);
					for(int i=0;i<suspendedAgentList.size();i++)
					{
						message.addReceiver(new AID(suspendedAgentList.get(i), AID.ISGUID));
					}
					message.setLanguage("Event");
					message.setOntology("Event");
					message.setContent(messageContent);
					send(message);
					System.out.println(messageContent);
				}
			};
			handlers.put(IntrospectionVocabulary.SUSPENDEDAGENT,suspendedAgentHandler);
			
			EventHandler resumedAgentHandler = new EventHandler() 
			{
				public void handle(Event ev) 
				{
					ResumedAgent ra = (ResumedAgent) ev;
					String messageContent = "ResumedAgent:";
					messageContent=messageContent+ra.getAgent().getName();
					jade.lang.acl.ACLMessage message=new jade.lang.acl.ACLMessage(jade.lang.acl.ACLMessage.INFORM);
					for(int i=0;i<resumedAgentList.size();i++)
					{
						message.addReceiver(new AID(resumedAgentList.get(i), AID.ISGUID));
					}
					message.setLanguage("Event");
					message.setOntology("Event");
					message.setContent(messageContent);
					send(message);
					System.out.println(messageContent);
				}
			};
			handlers.put(IntrospectionVocabulary.RESUMEDAGENT,resumedAgentHandler);
			
			EventHandler movedAgentHandler = new EventHandler() 
			{
				public void handle(Event ev) 
				{
					MovedAgent ma = (MovedAgent) ev;
					String messageContent = "MovedAgent:";
					messageContent=messageContent+ma.getAgent().getName();
					jade.lang.acl.ACLMessage message=new jade.lang.acl.ACLMessage(jade.lang.acl.ACLMessage.INFORM);
					for(int i=0;i<movedAgentList.size();i++)
					{
						message.addReceiver(new AID(movedAgentList.get(i), AID.ISGUID));
					}
					message.setLanguage("Event");
					message.setOntology("Event");
					message.setContent(messageContent);
					send(message);
					System.out.println(messageContent);
				}
			};
			handlers.put(IntrospectionVocabulary.MOVEDAGENT,movedAgentHandler);

			EventHandler killContainerRequestedHandler = new EventHandler() 
			{
				public void handle(Event ev) 
				{
					KillContainerRequested kcr = (KillContainerRequested) ev;
					String messageContent = "KillContainerRequested:";
					messageContent=messageContent+kcr.getContainer().getName();
					jade.lang.acl.ACLMessage message=new jade.lang.acl.ACLMessage(jade.lang.acl.ACLMessage.INFORM);
					for(int i=0;i<killContainerRequestedList.size();i++)
					{
						message.addReceiver(new AID(killContainerRequestedList.get(i), AID.ISGUID));
					}
					message.setLanguage("Event");
					message.setOntology("Event");
					message.setContent(messageContent);
					send(message);
					System.out.println(messageContent);
				}
			};
			handlers.put(IntrospectionVocabulary.KILLCONTAINERREQUESTED,killContainerRequestedHandler);
			
			EventHandler shutdownPlatformRequestedHandler = new EventHandler() 
			{
				public void handle(Event ev) 
				{
					ShutdownPlatformRequested spr = (ShutdownPlatformRequested) ev;
					String messageContent = "ShutdownPlatformRequested:";
					messageContent=messageContent+spr.getName();
					jade.lang.acl.ACLMessage message=new jade.lang.acl.ACLMessage(jade.lang.acl.ACLMessage.INFORM);
					for(int i=0;i<shutdownPlatformRequestedList.size();i++)
					{
						message.addReceiver(new AID(shutdownPlatformRequestedList.get(i), AID.ISGUID));
					}
					message.setLanguage("Event");
					message.setOntology("Event");
					message.setContent(messageContent);
					send(message);
					System.out.println(messageContent);
				}
			};
			handlers.put(IntrospectionVocabulary.SHUTDOWNPLATFORMREQUESTED,shutdownPlatformRequestedHandler);
					
		}
	}
}